#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/kdev_t.h>
#include <linux/slab.h>
#include <linux/gpio.h>
#include <linux/gpio/consumer.h> // 添加此头文件
#include <linux/delay.h>


struct ds18b20_data
{
    dev_t dev_num;
    struct cdev ds18b20_cdev;
    struct class *ds18b20_class;
    struct device *ds18b20_device;
    struct gpio_desc *ds18b20_gpio;
};

struct ds18b20_data *ds18b20;

void ds18b20_reset(void)
{
    gpiod_direction_output(ds18b20->ds18b20_gpio, 1);
    gpiod_set_value(ds18b20->ds18b20_gpio, 0);
    udelay(700);

    gpiod_set_value(ds18b20->ds18b20_gpio, 1);
    gpiod_direction_input(ds18b20->ds18b20_gpio);

    while ( gpiod_get_value(ds18b20->ds18b20_gpio));
    while ( !gpiod_get_value(ds18b20->ds18b20_gpio));
    udelay(480);
}

int ds18b20_open(struct inode *inode, struct file *file)
{
    return 0;
}

ssize_t ds18b20_read(struct file *file, char __user *buf, size_t size, loff_t *offs)
{
    return 0;
}

int ds18b20_release(struct inode *inode, struct file *file)
{
    return 0;
}

struct file_operations ds18b20_fops = {
    .open = ds18b20_open,
    .read = ds18b20_read,
    .release = ds18b20_release,
    .owner = THIS_MODULE,
};

int ds18b20_probe(struct platform_device *dev)
{
    int ret;
    printk("This is probe \n");
    ds18b20 = kzalloc(sizeof(*ds18b20), GFP_KERNEL);
    if (ds18b20 == NULL)
    {
        printk("kzalloc error\n");
        ret = -ENOMEM;
        goto error_0;
    }
    ret = alloc_chrdev_region(&ds18b20->dev_num, 0, 1, "myds18b20");
    if (ret < 0)
    {
        printk("alloc_chrdev_region error\n");
        ret = -EAGAIN;
        goto error_1;
    }

    cdev_init(&ds18b20->ds18b20_cdev, &ds18b20_fops);

    ds18b20->ds18b20_cdev.owner = THIS_MODULE;
    cdev_add(&ds18b20->ds18b20_cdev, ds18b20->dev_num, 1);

    ds18b20->ds18b20_class = class_create(THIS_MODULE, "sensors");
    if (IS_ERR(ds18b20->ds18b20_class))
    {
        printk("class_create error\n");
        ret = PTR_ERR(ds18b20->ds18b20_class);
        goto error_2;
    }

    ds18b20->ds18b20_device = device_create(ds18b20->ds18b20_class, NULL, ds18b20->dev_num, NULL, "ds18b20");
    if (IS_ERR(ds18b20->ds18b20_device))
    {
        printk("device_create error\n");
        ret = PTR_ERR(ds18b20->ds18b20_device);
        goto error_3;
    }

    ds18b20->ds18b20_gpio = gpiod_get_optional(&dev->dev, "ds18b20", 0);
    if (ds18b20->ds18b20_gpio == NULL)
    {
        ret = -EBUSY;
        goto error_4;
    }
    gpiod_direction_output(ds18b20->ds18b20_gpio, 1);

    return 0;
error_4:
    device_destroy(ds18b20->ds18b20_class, ds18b20->dev_num);

error_3:
    class_destroy(ds18b20->ds18b20_class);

error_2:
    cdev_del(&ds18b20->ds18b20_cdev);
    unregister_chrdev_region(ds18b20->dev_num, 1);

error_1:
    kfree(ds18b20);

error_0:
    return ret;
}

const struct of_device_id ds18b20_match_table[] = {
    {.compatible = "ds18b20"},
    {},
};

struct platform_driver ds18b20_driver = {
    .driver = {
        .owner = THIS_MODULE,
        .name = "ds18b20",
        .of_match_table = ds18b20_match_table,
    },
    .probe = ds18b20_probe,
};

static int __init ds18b20_init(void)
{
    int ret;
    ret = platform_driver_register(&ds18b20_driver);
    if (ret < 0)
    {
        printk("platform_driver_register error\n");
        return -1;
    }
    ds18b20_reset();
    return 0;
}

static void __exit ds18b20_exit(void)
{
    gpiod_put(ds18b20->ds18b20_gpio);
    device_destroy(ds18b20->ds18b20_class, ds18b20->dev_num);
    class_destroy(ds18b20->ds18b20_class);
    cdev_del(&ds18b20->ds18b20_cdev);
    unregister_chrdev_region(ds18b20->dev_num, 1);
    kfree(ds18b20);
    platform_driver_unregister(&ds18b20_driver);
}

module_init(ds18b20_init);
module_exit(ds18b20_exit);
MODULE_LICENSE("GPL");